package se.webbzon.boltzmann.effect;

import java.awt.Color;

import se.webbzon.oschi01.resourceset.ResourceSet;
import se.webbzon.oschi01.textureset.Texture3D;
import se.webbzon.oschi01.worldarea.WorldArea;
import se.webbzon.oschi01.worldobject.WorldMovableObject;
import se.webbzon.oschi01.worldobject.WorldObject;
import se.webbzon.oschi01.worldobject.WorldStaticObject;
import se.webbzon.oschi01.worldobject.appearance.AbstractAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.SimpleAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.XYPlaneAppearance3D;

public abstract class TextureEffect extends WorldMovableObject implements Effect {
	
	// The parent of this effect
	private WorldStaticObject parent;
	
	// The startup duration of the effect
	private final int duration;
		
	// The remaining duration of the effect
	private int remaining;
	
	/*============================================================
	Constructors
	============================================================*/
	
	/** Creates a new texture effect with a given set of registered methods, a parent
	 * and a given texture set. The duration (in number of steps) of the effect will 
	 * be equal to the size of the texture set. **/
	public TextureEffect(WorldStaticObject parent, ResourceSet<Texture3D> textureSet) {
		this(parent,textureSet,textureSet.size());
	}
	
	/** Creates a new texture effect with a given set of registered methods, a parent
	 * instance, a duration (in number of steps) and a given texture set. If the 
	 * duration is negative then the effect will last until termination. **/
	public TextureEffect(WorldStaticObject parent, ResourceSet<Texture3D> textureSet, int duration) {
		super(WorldObject.onStep,0,createAppearance(textureSet));
		this.parent = parent;
		this.duration = duration;
		remaining = duration;
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** This method is invoked when the texture effect begins. **/
	public abstract void onEffectBegin(WorldArea world);
	
	/** This method is invoked during each texture effect step. **/
	public abstract void onEffectStep(WorldArea world);
	
	/** This method is invoked when the texture effect ends. **/
	public abstract void onEffectEnd(WorldArea world);
	
	/** Returns the remaining duration of the effect. **/
	public int getDuration() {
		return remaining;
	}
	
	/** Returns the startup duration of the effect. **/
	public int getStartupDuration() {
		return duration;
	}
	
	/** Returns the parent of this texture effect. **/
	public WorldStaticObject getParent() {
		return parent;
	}
	
	/** Sets the color of this texture effect. **/
	public void setColor(Color color) {
		getSimpleAppearance().setColor(color);
	}
	
	/** Returns the color of this texture effect. **/
	public Color getColor() {
		return getSimpleAppearance().getColor();
	}
	
	/** Sets the transparency of this texture effect. **/
	public void setTransparency(float transparency) {
		getSimpleAppearance().setTransparency(transparency);
	}
	
	/** Returns the transparency of this texture effect. **/
	public float getTransparency() {
		return getSimpleAppearance().getTransparency();
	}
	
	@Override public final void launch(WorldArea world) {
		world.createInstance(this);
		onEffectBegin(world);
	}
	
	@Override public final void terminate(WorldArea world) {
		onEffectEnd(world);
		world.destroyInstance(this);
	}
	
	@Override public final void onStep(WorldArea world) {
		if (remaining == 0)
			terminate(world);
		else if (remaining > 0) {
			onEffectStep(world);
			remaining--;
		}
	}
	
	/*============================================================
	Private Methods
	============================================================*/
	
	/** Returns the simple 3d appearance of this texture effect. **/
	private SimpleAppearance3D getSimpleAppearance() {
		return (SimpleAppearance3D) getAppearance();
	}
	
	/** Creates the appearance of the texture effect. **/
	private static final AbstractAppearance3D createAppearance
													(ResourceSet<Texture3D> textureSet) {
		XYPlaneAppearance3D appearance = new XYPlaneAppearance3D(
										0,
										SimpleAppearance3D.TRANSPARENCY,false);
		appearance.setTextureSet(textureSet);
		appearance.setTextureSpeed(1);
		return appearance;
	}

}
